home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Interactive Reference Guide
/
C-C++ Interactive Reference Guide.iso
/
c_ref
/
csource4
/
203_01
/
yam3.c
< prev
next >
Wrap
Text File
|
1979-12-31
|
13KB
|
681 lines
/*
$title ('yam3.c: terminal mode utilities')
$date (9 nov 85)
*/
#include "yam.h"
#define BRKKEY STX
int overrun; /* true if data is lost */
/****************************************************************************
FUNCTION:
two-way conversation with remote -whatever.
Printer is buffered such that it needn't be as fast as the baudrate
as long as it eventually gets a chance to catch up.
This buffering also allows one to write the received data out to disk
after the conservation has started.
CALLING PARAMETERS:
none.
===========================================================================*/
term()
{
register c, cc;
unsigned charsent;
sayterm();
charsent = 0;
/* reset tab stop */
Ttycol = 0;
/* data flow flags */
Waitecho=Txwait=overrun=FALSE;
#ifdef IBMPC
/* enbable terminal mode */
enblcm(TRUE);
#endif
while(1)
{
/* IBMPC implementation uses assembly language interrupt routine for modem
input. Because the IBM terminal I/O is so painfully slow, interrupts were
added to avoid loosing characters and allow operation at >300 baud.*/
#ifndef IBMPC
/**** modem in ****/
if (MIREADY)
{
*bufcq = MICHAR;
if (!Ignrx)
bufcq++;
else
if(!index(*bufcq, rxnono))
bufcq++;
Timeout=0;
if(bufcq >= bufend)
{
Wrapped=TRUE;
bufcq=bufst;
}
if(--Nfree == LOWWATER)
MOCHAR(Xoffflg=TRUE);
else if(Nfree==0)
overrun = TRUE;
continue;
}
#endif
/**** keyboard ****/
if(CIREADY)
{
cfast = CICHAR;
if (doykbd(cfast))
return;
continue;
}
/**** console out ****/
if(bufcdq != bufcq)
if (COREADY)
{
switch(cfast = (*bufcdq & 0x7F) )
{
case '\b':
if(Ttycol)
--Ttycol;
break;
case '\t':
CONOUT(' ');
if (++Ttycol % tabstop)
continue;
else
goto chuckit;
case '\r':
Ttycol=0;
break;
case '\n':
/* continue transmit if enabled */
if(Txeoln==EOL_CRWAIT)
Waitecho=FALSE;
Ttycol=0;
break;
#ifdef XMODEM
case CPMEOF:
pstat("");
return;
/* bell */
case 007:
break;
#endif
default:
if (cfast==xoff)
{
#ifdef STATLINE
sayterm();
#endif
Txgo=FALSE;
goto chuckit;
}
else if (cfast==xon)
{
Txgo=TRUE;
#ifdef STATLINE
sayterm();
#endif
goto chuckit;
}
else if(Ctlview)
{
/* preceed with ~ if parity bit set */
if (cfast & 0x80)
{
CONOUT('~');
++Ttycol;
}
/* view control characters */
if (cfast < ' ')
{
CONOUT('^');
CONOUT(cfast|0x40);
Ttycol += 2;
goto chuckit;
}
} /* ctlview */
else
++Ttycol;
} /* switch */
/* resume file sending if waiting for go char */
if (cfast==GOchar && Txeoln==EOL_CRPROMPT)
Waitecho=FALSE;
CONOUT(cfast);
if(Echo)
{
sendbyte(cfast);
if(Chat && cfast== '\r')
{
CONOUT('\n');
#ifndef XMODEM
sendbyte('\n');
#endif
}
} /* echo */
chuckit:
/* if not receiving, buffer need not
be dumped. bump up number of free space left */
/* Some systems echo data sent(as in editor).
If receiving an echo term would emit dc3
when the buffer fills up. This will prevent that too */
if (!Rfile)
Nfree++;
if(++bufcdq >= bufend)
bufcdq=bufst;
continue;
}
/**** printer ****/
if (Pflag && (bufpcdq!=bufcq) && LPREADY)
{
LPOUT(*bufpcdq++ & 0177);
if (bufpcdq >= bufend)
bufpcdq=bufst;
}
/**** modem out ****/
if(MOREADY)
{
/* if transmit file is open(Tfile) and we are not waiting
for throttle(Txwait) and not waiting for an echo(!Waitecho)
and transmission is not suspended by xoff(Txgo) send char. */
if(Tfile && !Txwait && !Waitecho && Txgo)
{
/* get char from file */
c = getc(fin);
if(c==EOF)
{
closetx(FALSE);
#ifdef XMODEM
pstat("");
return;
#else
/* return to command mode on EOF if true */
if(Exoneof)
return;
/* explain were in term mode now */
sayterm();
#endif
}
/* wait for echoes to stop after waitnum characters.
Waitbunch set by 'et', Waitnum by 'pwn' */
if(Waitbunch && ++charsent==Waitnum)
{
charsent=0;
/* cause wait for echo */
if(Waitnum>1)
{
Waitecho=TRUE;
Timeout=0;
}
/* reset throttle wait parms */
else
{
Txwait=TRUE;
Txtimeout=Throttle;
}
}
/* end of line processing */
if(c=='\r')
{
switch(Txeoln)
{
case EOL_NL:
continue;
case EOL_CRPROMPT:
case EOL_CRWAIT:
Waitecho=TRUE;
Timeout=0;
case EOL_CR:
if(Tfile)
{
if((cc=getc(fin))!='\n')
ungetc(cc, fin);
}
break;
}
}
MOCHAR(c);
continue;
}
}
/* time to do something */
if(Timeout == Tpause)
{
Waitecho=FALSE;
/* dump buffer if full */
if(Xoffflg)
{
dumprxbuff();
/* allow term output to catch up */
if(bufcdq != bufcq)
continue;
/* allow printer output to catch up */
if(Pflag && bufpcdq != bufcq)
continue;
Xoffflg=FALSE;
MOCHAR(xon);
}
#ifdef CDO
if(CDO)
{
pstat("Carrier Lost");
return;
}
#endif
}
else
++Timeout;
/* buffer overflow */
if (overrun)
{
lpstat("\007OVERRUN: DATA LOST");
overrun = 0;
return;
}
if(--Txtimeout==0)
Txwait=FALSE;
}
} /* term */
/****************************************************************************
FUNCTION:
display the status information on entering term()
CALLING PARAMETERS:
none
===========================================================================*/
sayterm()
{
if(Tfile)
pstat("Sending '%s' %s", Tname, Txgo?"":"Stopped by XOFF");
else if(Rfile)
pstat("Term Receiving '%s'", Rname);
else
pstat("Term Function");
} /* sayterm */
/****************************************************************************
FUNCTION:
open a capture file and set the removal pointer to get max goods
called from main menu with t [filename].
CALLING PARAMETERS:
char *name:
pointer to file name to capture text to.
===========================================================================*/
opencapt(name)
char *name;
{
/* close any existing file */
dumprxbuff();
closerx(TRUE);
if(openrx(name)==ERROR)
return ERROR;
if(buffcdq<bufst)
buffcdq=bufst;
if(Wrapped)
buffcdq=bufcq+1;
if(buffcdq >= bufend)
buffcdq=bufst;
return OK;
} /* opencapt */
/****************************************************************************
FUNCTION:
dump circular buffer to disk
CALLING PARAMETERS:
none
===========================================================================*/
dumprxbuff()
{
register c;
Nfree=Bufsize;
if(!Rfile || buffcdq==NULL)
return OK;
while(buffcdq != bufcq)
{
c= *buffcdq++;
if(buffcdq >= bufend)
buffcdq=bufst;
switch(c &= 0177)
{
case 0:
continue;
case 0x1A: /* ^Z */
if(Zeof)
{
closerx(TRUE);
return OK;
}
else
break;
case 0x12:
if(Squelch)
{
Dumping=TRUE;
continue;
}
break;
case 0x14:
if(Squelch)
{
Dumping=FALSE;
continue;
}
break;
default:
break;
}
if(Dumping)
if(putc(c, fout)==ERROR)
{
printf("\nDisk Full\n");
closerx(FALSE);
return ERROR;
}
}
return OK;
} /* dumprxbuff */
/****************************************************************************
FUNCTION:
set buffer pointers back to start of data in buffer, or start of buffer
if the pointers have wrapped. Entering term after a rewind will cause
re-display of all captured data in buffer.
CALLING PARAMETERS:
none
===========================================================================*/
rewindcb()
{
bufcdq=buffcdq=bufpcdq=Wrapped?bufcq+1:bufst;
}
/****************************************************************************
FUNCTION:
replot redisplays the buffer contents thru putcty allowing xoff
number will represent how many lines to go back first
CALLING PARAMETERS:
number:
number of characters to re-display
===========================================================================*/
replot(number)
int number;
{
char doexit;
char *reptr;
char c;
char *smark;
char *p;
int count;
int n;
doexit=FALSE;
fromtop:
smark=reptr=bufmark=Wrapped?bufcq+1:bufst;
if(number)
{
reptr=bufcq;
/* backup up number lines. They will be displayed by nextline */
backsome:
/* backing up is confusing unless screen is cleared first */
for (n=1; n<TLENGTH; n++)
CONOUT('\n');
for(;;)
{
--reptr;
/* adjust for pointer wrap */
if(reptr<bufst)
{
if(Wrapped)
reptr = bufend-1;
else
{
reptr = bufst;
break;
}
}
/* hit begining of buffer */
if(reptr==bufcq)
break;
/* test for line count */
if((*reptr&0177)=='\n' && --number<=0)
break;
}
bufmark=reptr;
}
nextscreen:
count = TLENGTH - number;
/* display count lines */
nextline:
while(reptr != bufcq)
{
cfast= *reptr++ & 0177;
if(reptr >= bufend)
reptr=bufst;
if(c=putcty(cfast))
goto choose;
if (cfast=='\n' && --count<=0)
break;
}
if (doexit)
{
sayterm();
return;
}
#ifdef STATLINE
pstat("more ?");
#else
printf("\rmore ?");
#endif
c=getcty();
#ifdef STATLINE
pstat("");
#else
printf("\r \r");
#endif
choose:
/* Treat Control chars and letters the same */
switch((c|0x60)&0x7f)
{
case 'x':
doexit = TRUE;
number = TLENGTH;
reptr = bufcq;
goto backsome;
case 'o': /* /|0x60=o search command */
putcty('/');
smark = bufmark; /* search from start of screen */
gets(Utility.ubuf);
uncaps(Utility.ubuf);
/* FALL THROUGH TO */
case 'n': /* find next */
if ((p = cisubstr(smark, Utility.ubuf)) && p<bufend)
{
smark = 1 + (bufmark = reptr = p); /* +1 so n can work */
number = 1;
goto backsome;
} else
putcty(007);
/* FALL THROUGH TO */
case 'b': /* beginning of buffer */
number = 0;
goto fromtop;
case 'r': /* control-r or r = previous page */
case 'h': /* backspace */
number = TLENGTH-3;
reptr = bufmark;
goto backsome;
case 0x60: /* space bar = next page */
number = 3;
bufmark = reptr;
goto nextscreen;
case 'p': /* previous line */
number = 1;
reptr = bufmark;
goto backsome;
case 'j': /* linefeed */
bufmark = reptr;
count = 1;
goto nextline;
default:
return;
}
} /* replot */
/****************************************************************************
FUNCTION:
moment waits a moment and returns FALSE, if no character keyboarded in
the meantime, otherwise returns TRUE.
CALLING PARAMETERS:
none
===========================================================================*/
moment()
{
sleep(3);
if (CIREADY)
{
getcty();
return TRUE;
}
return FALSE;
} /* moment */
/****************************************************************************
FUNCTION:
chat function. Allow person to talk to operator at other end
CALLING PARAMETERS:
none
===========================================================================*/
dochat()
{
#ifdef XMODEM
printf("Exit chat with ^Z\n");
#endif
Chat=Ctlview=Hdx=Echo=TRUE;
term();
} /* dochat */
/****************************************************************************
FUNCTION:
Handle keyboard input. Returns TRUE iff caller should return to
command mode.
CALLING PARAMETERS:
cf:
char from keyboard. for IBM PC, keycode is in high byte, ascii
char is in low byte.
===========================================================================*/
doykbd(cf)
int cf;
{
switch (cf & 0x7F)
{
case ENQ:
if (moment()) /* ^E exits term */
break;
pstat(" ");
return TRUE;
case 0x12: /* ^r */
if (moment())
break;
replot(TLENGTH-1);
return;
case BRKKEY: /* BRK KEY sends break */
if (moment())
break;
sendbrk();
while (CIREADY)
getcty(); /* discard garbage */
return FALSE;
case '\r':
if(Hdx)
printf("\n");
if(Chat)
sendbyte('\n');
break;
default:
if (cf==xon)
{
if(Tfile && !Txgo)
{
Txgo=TRUE;
sayterm();
}
}
else if (cf==xoff)
{
if(Tfile && Txgo)
{
Txgo=FALSE;
sayterm();
}
}
}
#ifdef IBMPC
/* extended key codes for IBM PC. Low order byte is 0 */
if (!(cf & 0xFF))
switch (cf)
{
/* del key */
case 0x5300:
cf = 0x7F;
break;
default:
return FALSE;
}
#endif
/* send char to modem if not special key */
MOCHAR(cf & 0x7f);
if(Hdx)
CONOUT(cf);
return FALSE;
}/* doykbd */